#ifndef QQTMODBUSMANAGER_H
#define QQTMODBUSMANAGER_H

#include <QObject>

#include <QModbusClient>
#include <QModbusReply>
#include <QModbusRequest>
#include <QModbusDataUnit>

#include <qqt-qt.h>
#include <qqtcore.h>

#include <qqtindustrialcontrol_global.h>

class QQTINDUSTRIALCONTROLSHARED_EXPORT QQtModbusSession : public QObject
{
    Q_OBJECT
public:
    explicit QQtModbusSession ( QObject* parent = 0 );
    virtual ~QQtModbusSession();

    //timer
    void setTimeOut ( int timeout );
    QTimer* getTimer();

    //request
    int getModbusServerAddress();
    void setModbusServerAddress ( int serverAddress );

    QModbusRequest& modbusRequest();
    QModbusDataUnit& modbusDataUnit();
    QModbusDataUnit& modbusWriteDataUnit();

    //reply
    QModbusReply* getModbusReply();
    void setModbusReply ( QModbusReply* reply );

    //session name
    QString getModbusSessionName();
    void setModbusSessionName ( QString strSessionName );

private:
    //request unit
    QModbusDataUnit mModbusDataUnit;
    QModbusDataUnit mModbusWriteDataUnit;
    //request
    QModbusRequest mModbusRequest;
    //call back
    QModbusReply* m_pModbusReply;
    //call time out
    QTimer* m_pTimer;
    //calling url [user set] to make request
    int m_serverAddress;
    /**
     * @brief m_sessionName be a uuid [user set or auto]
     * talk with whom, which protocol, req content, all represented by this name;
     */
    QString m_strSessionName;
} ;

class QQTINDUSTRIALCONTROLSHARED_EXPORT QQtModbusSessionManager : public QObject
{
    Q_OBJECT
public:
    explicit QQtModbusSessionManager ( QObject* parent = 0 );
    virtual ~QQtModbusSessionManager();

    /**
     * @brief addModbusSession user new custom session and
     * please set session name different.
     * @return session name
     */
    QString addModbusSession ( QQtModbusSession* session );
    void removeModbusSession ( QQtModbusSession* session );
    /**
     * @brief newModbusSession
     * QQtModbusSessionManager create this session and
     * user set
     * @return
     */
    QQtModbusSession* newModbusSession();

    int getSessionCount() const;

    int getRequestServerAddressByReply ( QModbusReply* reply );
    QString getSessionNameByReply ( QModbusReply* reply );
    QQtModbusSession* getSessionByReply ( QModbusReply* reply );

    QModbusReply* getReplyHandlerByServerAddress ( int serverAddress );
    QString getSessionNameByServerAddress ( int serverAddress );
    QQtModbusSession* getSessionByServerAddress ( int serverAddress );

    QModbusReply* getReplyHandlerBySessionName ( QString strSessionName );
    int getRequestServerAddressBySessionName ( QString strSessionName );
    QQtModbusSession* getSessionBySessionName ( QString strSessionName );

    QModbusReply* getReplyHandlerByTimer ( QTimer* timer );
    int getRequestServerAddressByTimer ( QTimer* timer );
    QQtModbusSession* getSessionByTimer ( QTimer* timer );

    QModbusReply* getReplyHandler ( QQtModbusSession* session );
    int getRequestServerAddress ( QQtModbusSession* session );
    QString getSessionName ( QQtModbusSession* session );

protected:

private:
    QList<QQtModbusSession*> m_listModbusSession;
} ;

/**
 * @brief The QQtModbusManager class
 * Modbus通信过程管理器
 *
 * 使用方法类似于QQtWebAccessManager
 *
 * 使用Session管理通信回路
 * serverAddress + Request/DataUnit
 * Reply
 *
 * 内部进行了错误处理，超时处理。
 */
class QQTINDUSTRIALCONTROLSHARED_EXPORT QQtModbusManager : public QModbusClient
{
    Q_OBJECT
public:
    explicit QQtModbusManager ( QObject* parent = 0 );
    virtual ~QQtModbusManager() {}

    QQtModbusSessionManager* getModbusSessionManager();

    QQtModbusSession* sendRawRequest ( const QModbusRequest& request, int serverAddress );
    QQtModbusSession* sendReadRequest ( const QModbusDataUnit& read, int serverAddress );
    QQtModbusSession* sendWriteRequest ( const QModbusDataUnit& write, int serverAddress );
    QQtModbusSession* sendReadWriteRequest ( const QModbusDataUnit& read, const QModbusDataUnit& write, int serverAddress );

protected:

signals:
    void replyFinished ( QQtModbusSession* session );
    void replyTimeOut ( QQtModbusSession* session );
    void replyErrorOccurred ( QQtModbusSession* session );

public slots:

private slots:
    void errorOccurred ( QModbusDevice::Error error );
    void stateChanged ( QModbusDevice::State state );
    void timeoutChanged ( int newTimeout );

    void localReplyFinished();
    void localReplyTimeOut();
    void localReplyErrorOccurred ( QModbusDevice::Error );

private:
    QQtModbusSessionManager* manager;
};

#endif // QQTMODBUSMANAGER_H

